package gaml.java;


import java.util.HashMap;

/**
 * this class stores collection of "base class" serializers
 * classes, implementing IBaseClassSerialiser, serializing basic java
 * types like int and long and instances of String or Number or Map or List
 * into yaml
 * and deserializing them back
 *  
 * @author shnireck
 *
 */
public class ClassSerializerStore {
	HashMap <Class <?>, ClassSerializer <?>> serializers = new HashMap <Class <?>, ClassSerializer <?>> ();
	SerializerFactory complexFactory = null;
	SerializerFactory enumFactory = null;
	
	ClassSerializer <?> nullSerializer = null;
	
	
	/**
	 * adds new base class serializer to store
	 * @param <T> base class type
	 * @param clazz class for base class
	 * @param serializer serializer for objects of class
	 * @return store
	 */
	public <T> ClassSerializerStore register (ClassSerializer <T> serializer) {
		serializers.put (serializer.getObjectClass (), serializer);
		return this;
	}
	
	/**
	 * special serializer registration
	 * for serialization of primitive types and 
	 * descendants
	 * @param <T> type of serializing class objet
	 * @param clazz java class, which serializing object represents 
	 * @param serializer serializer for class
	 * @return host object
	 */
	public <T> ClassSerializerStore register (Class <T> clazz, ClassSerializer <?> serializer) {
		serializers.put (clazz, serializer);
		return this;
	}
	
	/**
	 * serializer for base class object
	 * @param <T> base class type
	 * @param clazz class of object, to user serializer on
	 * @return serializer
	 */
	public <T> ClassSerializer <T> get (Class <T> clazz) { return (ClassSerializer <T>) (null == clazz ? nullSerializer : serializers.get (clazz)); }
	
	/**
	 * check if we have serializer for some class in store
	 * @param <P> type of class
	 * @param clazz class, hose instance need to be serialized
	 * @return true if we have serializer for class, false otherwise
	 */
	public <P> boolean contains (Class <P> clazz) { return ((null == clazz) || (serializers.containsKey (clazz))); }
	
	/**
	 * @return complex serializer for types not known in store
	 */
	public <T> ClassSerializer <T> getDefault (Class <T> clazz) { return complexFactory.create (clazz); }
	
	/**
	 * get serializer for enumeration class
	 * @param <T> type of classs
	 * @param clazz enumeration class
	 * @return enumeration class field serializer
	 */
	public <T> ClassSerializer <T> getForEnum (Class <T> clazz) { return enumFactory.create (clazz); }
	
	/**
	 * @param complexFactory factory to create complex serializers
	 * @return host object
	 */
	public ClassSerializerStore setComplexFactory (SerializerFactory complexFactory) { this.complexFactory = complexFactory; return this; }
	
	/**
	 * set enum serializer factory to create serializers for java enumerations
	 * @param enumFactory factory class for enumeration serializers creation
	 * @return host store object
	 */
	public ClassSerializerStore setEnumFactory (SerializerFactory enumFactory) { this.enumFactory = enumFactory; return this; }
	
	/**
	 * set serializer for empty nodes and null java objects
	 * @param nullSerializer empty and nulls serializer
	 * @return host store object
	 */
	public ClassSerializerStore setNullSerializer (ClassSerializer <?> nullSerializer) { this.nullSerializer = nullSerializer; return this; }
}